90e9e2
@@ -203,19 +203,15 @@
public class SplitTransaction {
   }
 
   /**
-   * Run the transaction.
+   * Prepare the regions and region files.
    * @param server Hosting server instance.  Can be null when testing (won't try
    * and update in zk if a null server)
    * @param services Used to online/offline regions.
    * @throws IOException If thrown, transaction failed. Call {@link #rollback(Server, RegionServerServices)}
    * @return Regions created
-   * @throws KeeperException
-   * @throws NodeExistsException 
-   * @see #rollback(Server, RegionServerServices)
    */
-  public PairOfSameType<HRegion> execute(final Server server,
-      final RegionServerServices services)
-  throws IOException {
+  /* package */PairOfSameType<HRegion> createDaughters(final Server server,
+      final RegionServerServices services) throws IOException {
     LOG.info("Starting split of region " + this.parent);
     if ((server != null && server.isStopped()) ||
         (services != null && services.isStopping())) {
@@ -298,7 +294,21 @@
public class SplitTransaction {
       MetaEditor.offlineParentInMeta(server.getCatalogTracker(),
         this.parent.getRegionInfo(), a.getRegionInfo(), b.getRegionInfo());
     }
+    return new PairOfSameType<HRegion>(a, b);
+  }
 
+  /**
+   * Perform time consuming opening of the daughter regions.
+   * @param server Hosting server instance.  Can be null when testing (won't try
+   * and update in zk if a null server)
+   * @param services Used to online/offline regions.
+   * @param a first daughter region
+   * @param a second daughter region
+   * @throws IOException If thrown, transaction failed. Call {@link #rollback(Server, RegionServerServices)}
+   */
+  /* package */void openDaughters(final Server server,
+      final RegionServerServices services, HRegion a, HRegion b)
+      throws IOException {
     // This is the point of no return.  Adding subsequent edits to .META. as we
     // do below when we do the daughter opens adding each to .META. can fail in
     // various interesting ways the most interesting of which is a timeout
@@ -311,27 +321,64 @@
public class SplitTransaction {
     // still and the server shutdown fixup of .META. will point to these
     // regions.
     this.journal.add(JournalEntry.PONR);
+    boolean stopped = server != null && server.isStopped();
+    boolean stopping = services != null && services.isStopping();
+    // TODO: Is this check needed here?
+    if (stopped || stopping) {
+      // add 2nd daughter first (see HBASE-4335)
+      MetaEditor.addDaughter(server.getCatalogTracker(),
+          b.getRegionInfo(), null);
+      MetaEditor.addDaughter(server.getCatalogTracker(),
+          a.getRegionInfo(), null);
+      LOG.info("Not opening daughters " +
+          b.getRegionInfo().getRegionNameAsString() +
+          " and " +
+          a.getRegionInfo().getRegionNameAsString() +
+          " because stopping=" + stopping + ", stopped=" + stopped);
+    } else {
       // Open daughters in parallel.
-    DaughterOpener aOpener = new DaughterOpener(server, services, a);
-    DaughterOpener bOpener = new DaughterOpener(server, services, b);
-    aOpener.start();
-    bOpener.start();
-    try {
-      aOpener.join();
-      bOpener.join();
-    } catch (InterruptedException e) {
-      Thread.currentThread().interrupt();
-      throw new IOException("Interrupted " + e.getMessage());
-    }
-    if (aOpener.getException() != null) {
-      throw new IOException("Failed " +
-        aOpener.getName(), aOpener.getException());
-    }
-    if (bOpener.getException() != null) {
-      throw new IOException("Failed " +
-        bOpener.getName(), bOpener.getException());
+      DaughterOpener aOpener = new DaughterOpener(server, a);
+      DaughterOpener bOpener = new DaughterOpener(server, b);
+      aOpener.start();
+      bOpener.start();
+      try {
+        aOpener.join();
+        bOpener.join();
+      } catch (InterruptedException e) {
+        Thread.currentThread().interrupt();
+        throw new IOException("Interrupted " + e.getMessage());
+      }
+      if (aOpener.getException() != null) {
+        throw new IOException("Failed " +
+          aOpener.getName(), aOpener.getException());
+      }
+      if (bOpener.getException() != null) {
+        throw new IOException("Failed " +
+          bOpener.getName(), bOpener.getException());
+      }
+      if (services != null) {
+        try {
+          // add 2nd daughter first (see HBASE-4335)
+          services.postOpenDeployTasks(b, server.getCatalogTracker(), true);
+          services.postOpenDeployTasks(a, server.getCatalogTracker(), true);
+        } catch (KeeperException ke) {
+          throw new IOException(ke);
+        }
+      }
     }
+  }
 
+  /**
+   * Finish off split transaction, transition the zknode
+   * @param server Hosting server instance.  Can be null when testing (won't try
+   * and update in zk if a null server)
+   * @param services Used to online/offline regions.
+   * @param a first daughter region
+   * @param a second daughter region
+   * @throws IOException If thrown, transaction failed. Call {@link #rollback(Server, RegionServerServices)}
+   */
+  /* package */void transitionZKNode(final Server server, HRegion a, HRegion b)
+      throws IOException {
     // Tell master about split by updating zk.  If we fail, abort.
     if (server != null && server.getZooKeeper() != null) {
       try {
@@ -371,7 +418,26 @@
public class SplitTransaction {
     // Leaving here, the splitdir with its dross will be in place but since the
     // split was successful, just leave it; it'll be cleaned when parent is
     // deleted and cleaned up.
-    return new PairOfSameType<HRegion>(a, b);
+  }
+
+  /**
+   * Run the transaction.
+   * @param server Hosting server instance.  Can be null when testing (won't try
+   * and update in zk if a null server)
+   * @param services Used to online/offline regions.
+   * @throws IOException If thrown, transaction failed. Call {@link #rollback(Server, RegionServerServices)}
+   * @return Regions created
+   * @throws KeeperException
+   * @throws NodeExistsException 
+   * @see #rollback(Server, RegionServerServices)
+   */
+  public PairOfSameType<HRegion> execute(final Server server,
+      final RegionServerServices services)
+  throws IOException {
+    PairOfSameType<HRegion> regions = createDaughters(server, services);
+    openDaughters(server, services, regions.getFirst(), regions.getSecond());
+    transitionZKNode(server, regions.getFirst(), regions.getSecond());
+    return regions;
   }
 
   /*
@@ -379,17 +445,14 @@
public class SplitTransaction {
    * If we fail, abort this hosting server.
    */
   class DaughterOpener extends Thread {
-    private final RegionServerServices services;
     private final Server server;
     private final HRegion r;
     private Throwable t = null;
 
-    DaughterOpener(final Server s, final RegionServerServices services,
-        final HRegion r) {
+    DaughterOpener(final Server s, final HRegion r) {
       super((s == null? "null-services": s.getServerName()) +
         "-daughterOpener=" + r.getRegionInfo().getEncodedName());
       setDaemon(true);
-      this.services = services;
       this.server = s;
       this.r = r;
     }
@@ -405,7 +468,7 @@
public class SplitTransaction {
     @Override
     public void run() {
       try {
-        openDaughterRegion(this.server, this.services, r);
+        openDaughterRegion(this.server, r);
       } catch (Throwable t) {
         this.t = t;
       }
@@ -420,26 +483,12 @@
public class SplitTransaction {
    * @throws IOException
    * @throws KeeperException
    */
-  void openDaughterRegion(final Server server,
-      final RegionServerServices services, final HRegion daughter)
+  void openDaughterRegion(final Server server, final HRegion daughter)
   throws IOException, KeeperException {
-    boolean stopped = server != null && server.isStopped();
-    boolean stopping = services != null && services.isStopping();
-    if (stopped || stopping) {
-      MetaEditor.addDaughter(server.getCatalogTracker(),
-        daughter.getRegionInfo(), null);
-      LOG.info("Not opening daughter " +
-        daughter.getRegionInfo().getRegionNameAsString() +
-        " because stopping=" + stopping + ", stopped=" + server.isStopped());
-      return;
-    }
     HRegionInfo hri = daughter.getRegionInfo();
     LoggingProgressable reporter = server == null? null:
       new LoggingProgressable(hri, server.getConfiguration());
-    HRegion r = daughter.openHRegion(reporter);
-    if (services != null) {
-      services.postOpenDeployTasks(r, server.getCatalogTracker(), true);
-    }
+    daughter.openHRegion(reporter);
   }
 
   static class LoggingProgressable implements CancelableProgressable {
